using System.Collections.Generic;
using GraphSynth;
using GraphSynth.Representation;
using GraphSynth.Search;

namespace GearSynth
{
    public class MakeGearRules : SearchProcess
    {
        /// <summary>
        ///   Gets the text describing that is displayed in the menu. It must be overridden in the methods.
        /// </summary>
        /// <value>The text.</value>
        public override string text
        {
            get { return "Create Gear Library"; }
        }

        /// <summary>
        ///   Runs the instance of the plugin that is initialized by GraphSynth.
        ///   This is basically a best-first tree search for the first solution
        ///   that doesn't violate constraints.
        /// </summary>
        protected override void Run()
        {
            var GearLibrary = GearFamily.Load();
            var templateRuleSet = rulesets[0];
            /* first simply copy all the settings from the template to the new ruleset. */
            var libraryRuleSet = new ruleSet
                                     {
                                         choiceMethod = templateRuleSet.choiceMethod,
                                         filer = settings.filer as BasicFiler,
                                         finalCandidates = templateRuleSet.finalCandidates,
                                         generationAfterChoice = templateRuleSet.generationAfterChoice,
                                         generationAfterCycleLimit = templateRuleSet.generationAfterCycleLimit,
                                         generationAfterNormal = templateRuleSet.generationAfterNormal,
                                         generationAfterNoRules = templateRuleSet.generationAfterNoRules,
                                         generationAfterTriggerRule = templateRuleSet.generationAfterTriggerRule,
                                         interimCandidates = templateRuleSet.interimCandidates,
                                         name = "GearLibraryRuleSet",
                                         nextGenerationStep = templateRuleSet.nextGenerationStep,
                                         rulesDir = templateRuleSet.rulesDir,
                                         RuleSetIndex = templateRuleSet.RuleSetIndex,
                                         TriggerRuleNum = templateRuleSet.TriggerRuleNum
                                     };
            foreach (var family in GearLibrary)
                foreach (var rule in templateRuleSet.rules)
                    if (rule.comment.Contains(family.gearType.ToString()))
                    {
                        var newRule = new grammarRule
                                          {
                                              comment = rule.comment + " for gear family " + family.label,
                                              containsAllGlobalLabels = rule.containsAllGlobalLabels,
                                              embeddingRules = rule.embeddingRules,
                                              Flip = rule.Flip,
                                              induced = rule.induced,
                                              L = rule.L.copy(),
                                              MatchRShapes = rule.MatchRShapes,
                                              name = rule.name + " for gear family " + family.label,
                                              negateLabels = new List<string>(rule.negateLabels),
                                              OrderedGlobalLabels = rule.OrderedGlobalLabels,
                                              Projection = rule.Projection,
                                              R = rule.R.copy(),
                                              Rotate = rule.Rotate,
                                              Scale = rule.Scale,
                                              spanning = rule.spanning,
                                              Skew = rule.Skew,
                                              termination = rule.termination,
                                              TransformNodeShapes = rule.TransformNodeShapes,
                                              Translate = rule.Translate,
                                              UseShapeRestrictions = rule.UseShapeRestrictions
                                          };
                        var sourceGear = newRule.L.nodes.Find(n =>
                                                              (n.localLabels.Contains("gear") &&
                                                               n.localLabels.Contains("source")));
                        if (sourceGear != null)
                            sourceGear.localLabels.Add(family.label);
                        foreach (var node in newRule.R.nodes)
                            if (node.localLabels.Contains("gear"))
                                node.localLabels.Add(family.label);
                        var filename = "GearLibrary\\" + newRule.name + ".grxml";
                        libraryRuleSet.ruleFileNames.Add(filename);
                        filename = rulesDirectory + filename;
                        Save(filename, newRule, true);
                        libraryRuleSet.Add(newRule);
                    }
            Save(rulesDirectory + "GearLibraryRuleSet.rsxml", libraryRuleSet);
            rulesets[0] = libraryRuleSet;
        }

    }
}